﻿using Daq.Models;
using Daq.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;

namespace Daq.Devices
{

    public class JsonRpcRequest
    {
        //public string Jsonrpc { get; set; } = "2.0";
        [JsonPropertyName("method")]
        public object Method { get; set; }
        [JsonPropertyName("params")]
        public object Params { get; set; }
        [JsonPropertyName("id")]
        public int Id { get; set; }
    }

    

    public class JsonRpcResponse
    {
        //public string Jsonrpc { get; set; }
        [JsonPropertyName("id")]
        public int Id { get; set; }
        [JsonPropertyName("result")]
        public object Result { get; set; }
        [JsonPropertyName("error")]
        public object Error { get; set; }
    }

    internal class DX2100 : DaqBase
    {
        public override async Task CloseAsync(CancellationToken token)
        {
            try
            {
                // 关闭连接
                await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
            }
            catch (Exception ex) 
            {
                Debug.WriteLine(ex.Message);
            }
            client?.Dispose();
            client = new ClientWebSocket();
            isRunning = false;
        }
        public override string? Model => "DX2100";
        public string? Address { get; set; }

        public override async Task<bool> EnsureConnection(CancellationToken token)
        {

            //if(client.State == WebSocketState.Open || client.State == WebSocketState.Connecting)
            //{
            //    return true;
            //}

            //if(client.State == WebSocketState.Aborted)
            //{
            //    client.Dispose();
            //    client = new ClientWebSocket();
            //}

            if (client != null && client.State == WebSocketState.Open)
            {
                return true;
            }

            client = new ClientWebSocket();
            if (string.IsNullOrWhiteSpace(Address)) return false;
            var uri = new Uri($"ws://{Address}:8000/websocket");

            var clientTask = client.ConnectAsync(uri, token);
            var timeOutTask = Task.Delay(2000, token);
            var completedTask = await Task.WhenAny(clientTask, timeOutTask);
            if(completedTask == timeOutTask)
            {
                token.ThrowIfCancellationRequested();
            }
            return true;
        }

        byte[] bufferResponse = new byte[1024000];
        private bool isRunning = false;
        private DateTime daqTime;
        public override async Task<int> FetchAsync(int timeout, CancellationToken token)
        {
            await EnsureConnection(token);
            if (!isRunning)
            {
                await SendRpcRequest("start", null, 0, token);
                try
                {
                    var response = await ReceiveRpcResponse(token);
                    if (response.Result.ToString() == "0")
                    {
                        isRunning = true;
                        daqTime = DateTime.Now;
                    }
                }
                catch(Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
                return 1;
            }
            else
            {
                WebSocketReceiveResult result;
                // 创建一个延迟任务，该任务将在超时时间后完成
                var delayTask = Task.Delay(timeout, token);

                CancellationTokenSource source = new();

                // 同时开始接收数据
                var receiveTask = client.ReceiveAsync(new ArraySegment<byte>(bufferResponse), source.Token);

                // 等待两个任务中的任何一个完成
                Task completedTask = await Task.WhenAny(receiveTask, delayTask);

                // 检查哪个任务完成
                if (completedTask == receiveTask)
                {
                    // 接收成功
                    result = await receiveTask;

                    if(result.MessageType != WebSocketMessageType.Binary)
                    {
                        return 1;
                    }

                    var response = Encoding.UTF8.GetString(bufferResponse, 0, result.Count);
                    //Debug.WriteLine($"Received: {result.Count}");

                    int groupCount = bufferResponse[0] + (bufferResponse[1] << 8) + (bufferResponse[2] << 16) + (bufferResponse[3] << 24);
                    //int chCount = (result.Count - 4) / groupCount / 4;
                    //Debug.WriteLine($"chCount: {chCount}");
                    if (chCount != (result.Count - 4) / groupCount / 4)
                    {
                        Debug.WriteLine("数据错误");
                        return 1;
                    }

                    int index = 4;
                    //Random random = new Random();
                    for (int i = 0; i < groupCount; i++)
                    {
                        DaqMeasureData data = new DaqMeasureData();
                        daqTime = daqTime.AddMilliseconds(1);
                        data.Time = daqTime;
                        data.RawValue = new int[chCount];


                        for (int ch = 0; ch < chCount; ch++)
                        {
                            data.RawValue[ch] = bufferResponse[index] + (bufferResponse[index + 1] << 8) + (bufferResponse[index + 2] << 16) + (bufferResponse[index + 3] << 24);
                            //data.RawValue[ch] = (int)random.NextInt64(10, 100) + 3300;
                            //if(ch >= 48 && ch <= 55)
                            //{
                            //    data.RawValue[ch] = (int)random.NextInt64(10, 100) + 24000;
                            //}
                            index += 4;
                        }
                        //data.RawValue[56] = 33;
                        //if(data.RawValue[56] != 5600)
                        //Debug.WriteLine($"{chCount},{data.RawValue[56]}");
                        //Debug.WriteLine(string.Join(',', data.RawValue));
                        MeasureDataQueue.Enqueue(data);
                    }
                    return groupCount;
                }
                else if (completedTask == delayTask)
                {
                    source.Cancel();
                }

                return 1;
            }
        }

        private int chCount = -1;
        public override async Task<ChannelModel[]?> GetChannelsInfoAsync(CancellationToken token)
        {
            await GetDaqSettings(token);
            var chs = new List<ChannelModel>();
            chCount = DaqSettings.Channels.Where(ch => ch.Status == true).Count();
            int index = 1;
            if(DaqSettings.Channels != null)
            {
                foreach (var ch in DaqSettings.Channels)
                {
                    if (!ch.Status) continue;
                    chs.Add(new ChannelModel
                    {
                        Type = DaqDevice.GetChannelType(ch.Unit),
                        Unit = ch.Unit,
                        RangeMax = 100,
                        RangeMin = 0,
                        Index = index++,
                        IsEnabled = ch.Status,
                        Color = ch.Color,
                        Name = ch.Alias,
                        Digits = ch.Digits
                    });
                }
            }
            MeasureData.Channels = [.. chs];
            return [.. chs];
        }

        public override Task<double> GetSampleRateAsync(CancellationToken token)
        {
            return Task.FromResult(0.001);
        }

        private async Task SendRpcRequest(string methodName, object parameters, int id, CancellationToken token)
        {
            await EnsureConnection(token);
            // 发送JSON-RPC请求
            var request = new JsonRpcRequest
            {
                Method = methodName,
                Params = parameters,
                Id = id
            };
            var json = JsonSerializer.Serialize(request);
            var buffer = Encoding.UTF8.GetBytes(json);
            var segment = new ArraySegment<byte>(buffer);
            await client?.SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None);
        }

        private async Task<JsonRpcResponse> ReceiveRpcResponse(CancellationToken token)
        {
            await EnsureConnection(token);
            var result = await client.ReceiveAsync(new ArraySegment<byte>(bufferResponse), CancellationToken.None);
            var response = Encoding.UTF8.GetString(bufferResponse, 0, result.Count);
            Debug.WriteLine(response);
            return JsonSerializer.Deserialize<JsonRpcResponse>(response);
        }

        private ClientWebSocket client;

        private async Task<byte[]> ReceiveAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            WebSocketReceiveResult result;
            // 创建一个延迟任务，该任务将在超时时间后完成
            var delayTask = Task.Delay(timeout, cancellationToken);

            // 同时开始接收数据
            var receiveTask = client.ReceiveAsync(new ArraySegment<byte>(bufferResponse), CancellationToken.None);

            // 等待两个任务中的任何一个完成
            Task completedTask = await Task.WhenAny(receiveTask, delayTask);

            // 检查哪个任务完成
            if (completedTask == receiveTask)
            {
                // 接收成功
                result = await receiveTask;
                byte[] array = new byte[result.Count];
                Debug.WriteLine(result.Count);
                Array.Copy(bufferResponse.ToArray(), array, result.Count);
                return array;
            }
            else if (completedTask == delayTask)
            {
                cancellationToken.ThrowIfCancellationRequested();
            }
            return null;
        }

        public static string TruncateUtf8String(string input, int maxLength)
        {
            byte[] encodedBytes = Encoding.UTF8.GetBytes(input);

            // 如果原始字符串转换后的长度超过最大长度，则进行截断
            if (encodedBytes.Length > maxLength)
            {
                // 使用 StringBuilder 来构建截断后的字符串
                var sb = new System.Text.StringBuilder();
                int bytesWritten = 0;

                for (int i = 0; i < input.Length; i++)
                {
                    char c = input[i];
                    byte[] currentCharBytes = Encoding.UTF8.GetBytes(c.ToString());

                    // 检查添加当前字符后是否超过了最大长度
                    if (bytesWritten + currentCharBytes.Length <= maxLength)
                    {
                        sb.Append(c);
                        bytesWritten += currentCharBytes.Length;
                    }
                    else
                    {
                        // 如果添加当前字符会导致长度超过最大长度，且当前字符是多字节字符，则跳过该字符
                        if (currentCharBytes.Length > 1)
                        {
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                // 返回截断后的字符串
                return sb.ToString();
            }

            // 如果不需要截断，则直接返回原始字符串
            return input;
        }

        public override async Task SendDaqSettings(CancellationToken token)
        {
            if (DaqSettings == null)
            {
                return;
            }
            foreach(var ch in DaqSettings.Channels)
            {
                ch.Alias = TruncateUtf8String(ch.Alias, 32 - 1);
                ch.Unit = TruncateUtf8String(ch.Unit, 16 - 1);
            }
            string str = JsonSerializer.Serialize(DaqSettings);
            await SendRpcRequest("set_daq_info", new string[] { str }, 0, token);
            Debug.WriteLine("设置DAQ参数：" + str);
            var response = await ReceiveRpcResponse(token);
        }
        public override async Task<bool> GetSetDaqSettingsStatus(CancellationToken token)
        {
            await SendRpcRequest("get_daq_info_set_status", null, 0, token);
            var response = await ReceiveRpcResponse(token);
            var result = response.Result.ToString();
            //if ()
            //{
            //    return false;
            //}
            Debug.WriteLine("result=" + result);
            return result == "0";
        }

        private async Task<DaqSettings?> GetDaqSettings(CancellationToken token)
        {
            await SendRpcRequest("get_daq_info", null, 0, token);
            string responseText = "";
            // 接收服务器的响应
            //var result = await client.ReceiveAsync(new ArraySegment<byte>(bufferResponse), CancellationToken.None);
            DaqSettings = new();
            for (int i = 0; i < 10; i++)
            {
                try
                {
                    var result = await ReceiveAsync(TimeSpan.FromMilliseconds(1000), new CancellationToken());
                    if (result == null || result.Length == 0) continue;
                    var response = Encoding.UTF8.GetString(bufferResponse, 0, result.Length);
                    Debug.WriteLine($"Received {response}");
                    JsonRpcResponse r = JsonSerializer.Deserialize<JsonRpcResponse>(response);
                    responseText = r.Result.ToString();
                    DaqSettings = JsonSerializer.Deserialize<DaqSettings>(responseText);
                    break;
                }
                catch (Exception ex)
                {
                    //await File.AppendAllTextAsync("./response.txt", $"{DateTime.Now.ToString()}\n{responseText}\n\n");
                    Debug.WriteLine($"Error: {ex.Message}");
                }
            }

            if (DaqSettings != null && DaqSettings.Channels != null)
            {
                int index = 1;
                foreach (var ch in DaqSettings.Channels)
                {
                    ch.Index = index;
                    ch.GroupIndex = (index - 1) / 8 + 1;
                    index++;
                }
            }

            //从配置文件中获取通道配置
            return DaqSettings;
        }

        public override async Task OpenAsync(string address, CancellationToken token)
        {
            this.Address = address;
            await EnsureConnection(token);
        }
       
        public override async Task<bool> ModifyAddress(object address, CancellationToken token)
        {
            if (address is string[] array && array.Length == 2)
            {
                await SendRpcRequest("set_ip_address", array, 0, token);
                //var result = await ReceiveRpcResponse(token);
                return true;
            }
            return false;
        }

        public override async Task StopAsync(CancellationToken token)
        {
            try
            {
                await SendRpcRequest("stop", null, 0, token);
                await ReceiveRpcResponse(token);
            }
            catch { }
        }

        public override Task<DaqInfo?> GetDaqInfo(CancellationToken token)
        {
            throw new NotImplementedException();
        }

        public override Task SendDaqSettings(DaqInfo daqInfo, CancellationToken token)
        {
            throw new NotImplementedException();
        }
    }
}
